LOVE TOKENS
----------

Written for WOOT 2020 by Andy Jenkinson (uglifruit)

For the ZX Spectrum.

Musically enhanced for Spectrums with AY Chips

(128K models, or 48K models with an exernal AYchip eg. Melodik AY-3-8192 Soundbox or ZX-AY add-on).


Two versions are supplied :

LOVE-TOKENS-(BASIC and AY).tap
LOVE-TOKENS-(BASIC and AY - ALTERNATE - USR0 version).tap  *

* Use this version only if the other version causes incompatibility with unusual peripherals/Spectrum models.  This should be loaded in 48K/USR0 mode.


------------------------------------------------------------------------------------------

This piece was borne out of wanting to write something using only the BASIC Token Keywords as printed on the original ZX Spectrum.  ("PRINT, LOAD, SAVE..." etc.)  As such this can be considered A "Constrained Writing" Poem (the term an any English graduates might use).

Once I had written the text using just BASIC Tokens, the task became to illustrate it.  To continue the theme, this was done exclusively using BASIC PLOT, DRAW and CIRCLE commands.

There is a beeper tune at the beginning, and an AY tune that plays throughout (if your machine has an AY chip).




13 Things Of Moderate Interest (Maybe)
--------------------------------------

1. The text of the 'poem' itself is only 169 bytes long, and stored in the variable a$.  This initially had the carriage returns (CHR$13) within it, but this made LISTing the program awkward once it was inserted into line 1 LET a$="VAL blah blah etc...", I decided to replace the control codes with 'A' and 'B'.  The command PRINT a$ gives the whole text.

2. The text string was POKED into the LET a$="VAL etc" statement, as it is inconvenient to type some of the keywords (especially those requiring the K cursor).  This necessitated translating the tokens into their character codes (eg. PRINT=245), and finding the BASIC statement in RAM.  I now have an excel spreadsheet of the ZX Spectrum Character Set for this purpose.

3. The graphic data (which takes up the bulk of the BASIC listing as DATA statements) was created using a short routine I wrote (also in BASIC).  This very primitive drawing tool allowed me to choose positions on the screen to plot/draw lines to, then gave me numbers I could copy into DATA statements.  In hindsight I could have stored this data more efficiently.  I did experiment with moving all of this data into a variable numeric ARRAY - but this was considerably slower to access than the RESTORE {calculated line-number} technique I used in this listing.  Incidentally I quite like the aesthetic of the line art - and the DRAW statements are actually pretty speedy - though the CIRCLE statements feel painfully slow.

4. The BEEPER MUSIC is an interesting piece of Minimalism (for those who might care, and have an interest in music theory).  The note vales are stored in a DATA statements at line 7000, 7005 and 7010.  (And played by the routine in lines 85-96).  The data is basically simple arpeggios of the chords [Am, Am, Dm, E7] which then repeats once, and then does a slight variation with alternate descending and climbing runs across each chord.  It's in 6/8, so this would - in theory take 6*4*3 = 72 notes before it repeats.  However it is (deliberately) missing out each sixth note - thus creating a gap.  This is clearly audible in the tune (which is audibly made up of 5 note phrases).  The interesting thing is that the data set is only 71 notes long - so upon repeating (after it has been through all 71 notes) it starts again; thus upon repeating, the first note played is one note later in the data.  This means a different note is skipped on the each phrase on the second pass.  On the third pass there is another shift by one, and so on, and thus we hear different musical phrases each time which appear to have different stresses each time.

5. The V+0.771 in the BEEP statement is to approximately get the beeper and AY music in tune - making the transition from the intro beeper tune to the 'in game' slightly tune less jarring.

6. The AY MUSIC.  This is something I've not seen done before in a BASIC program, and caused me numerous headaches.  I've written a m/code interrupt mode 2 routine, called every 50th of a second, which plays the music and jumps to the normal ROM interrupt routine to update the Keyboard for BASIC etc.  The RANDOMIZE USR 49060 statement sets up the IM2 stuff.  I wasn't sure how much music I'd be creating, so I made sure the CLEAR 49059 was sufficiently high to allow the BASIC program to fit - but also left plenty of headroom for music, IM2 routine, and IM2 vector table.  Unless you read very slowly I doubt the music will have looped by the time you finish reading the text.

7. Exiting to BASIC.  Exiting to BASIC has one of two effects - if everything has gone to plan you are left with the music playing in the background (ad infinitum) whilst you enjoy the listing of the program in 48K Basic mode.  It can also - with certain combinations of attached peripherals on a 128K model - crash upon exiting to BASIC.  I could prevent this, by restoring IM1 at the end of the program ... but I enjoyed the unsettling effect of being back at the Basic prompt with the music still playing so I wanted this to be the default - regardless of Spectrum model being used.  Which led me to explore...

8. Forcing USR0 (48K Spectrum Mode), regardless of the Spectrum you're using.  The loader has an intersting first line that I can't take full credit for.  I've shameless used Slavomir Labsky's work (https://busy.speccy.cz/tvorba/usr0.htm) to force USR0 mode (so move into 48K mode on a 128K Spectrum), and continue to then run the rest of the BASIC program.  There is a possibility that this could be incompatibile with some hardware configurations/peripherals - in which case the 'Alternative' .tap file (which should be loaded from 48K BASIC mode on a 128K Spectrum) is provided.  The normal version should work though in 99% of cases, I think.  (I hope).

9. There is a cheeky 16bytes of m/code that I've snuck into the REM statement in the loader that "checkerboards" the screen, allowing the 'loading screen' to be made up entirely of attribute data.  (And it is me pointing out that the 'O' key is by far the funniest one on the rubber keyed Speccy.  "Oh! Peek at him Poking Out!" the Keywords seem to say.  Matron!!)

10. The filename for the loader is much longer than 'allowed' thanks to having Keyword Tokens in it.  To stay in keeping with the Basic Keyword Token theme.

11. RANDOMIZE USR 49093 stops the music (that's press the T Key [RANDOMIZE], then Sym+Caps to get enter 'Extended' mode and then L [USR], then 4,9,0,9,3 [enter] for those not used to 48K basic).  Not that you'll want to stop the music, you should just let it play.  And play.

12. RAMDOMIZE USR 3582 - used throughout the BASIC program, is the ROM routine that scrolls the screen.  Don't you miss the SCROLL command from BASIC on the ZX81?  I do.

13. As Dave (R-Tape) suggested, 'Love Tokens' doesn't feel a million miles away from Chris Sievey's excellent 'Camouflage' (https://www.youtube.com/watch?v=8u9ZyV-BHFA).  Remarkably, this 'animated pop video' was written for the ZX81 and was recorded on the back of the 7inch single.  Perhaps next time I'll try making something that syncs with the AY music.  THERE's a challenge.


I hope you enjoy this.

Andy 
Dec 2020.

